#!/usr/bin/env python
# Copyright (C) 2016 Cuckoo Foundation.
# This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org
# See the file 'docs/LICENSE' for copying permission.

import argparse
import fcntl
import os
import socket
import struct
import sys

sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))

from lib.cuckoo.common.path_utils import path_delete, path_exists
from lib.cuckoo.core.rooter import rooter, vpns
from lib.cuckoo.core.startup import init_rooter, init_routing

SIOCGIFADDR = 0x8915


def get_ip_address(interface):
    """Retrieves the local IP address of a network interface."""
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    buf = fcntl.ioctl(s.fileno(), SIOCGIFADDR, struct.pack("256s", interface))
    return socket.inet_ntoa(buf[20:24])


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("server", nargs="?", default="/tmp/cuckoo-rooter", help="Unix socket path of the server")
    parser.add_argument("client", nargs="?", default="/tmp/cuckoo-vpncheck", help="Unix socket path of this client")
    parser.add_argument("name", required=True, help="VPN name")
    parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose logging")
    args = parser.parse_args()

    if path_exists(args.client):
        path_delete(args.client)

    init_rooter()
    init_routing()

    error = 0
    for vpn, status in rooter("vpn_status", "args.name").items():
        if vpn not in vpns:
            print("Not a configured VPN", vpn)
            continue

        is_nic_available = rooter("nic_available", vpns[vpn].interface)["output"]
        if not is_nic_available:
            print("VPN is no longer available", vpn, file=sys.stderr)
            error = 1
            continue

        ipaddr = get_ip_address(vpns[vpn].interface)

        rooter("forward_enable", vpns[vpn].interface, vpns[vpn].interface, ipaddr)
        rooter("srcroute_enable", vpns[vpn].rt_table, ipaddr)

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        try:
            sock.bind((ipaddr, 0))
            sock.connect(("myip.cuckoo.sh", 80))
            sock.send("GET / HTTP/1.0\r\nHost: myip.cuckoo.sh\r\n\r\n")
            ret = sock.recv(4096).split("\r\n\r\n", 1)[-1]

            if args.verbose:
                print(vpns[vpn].name, ipaddr, ret)
        except socket.error:
            print("Unable to connect through VPN", vpn, file=sys.stderr)
            error = 1

        rooter("forward_disable", vpns[vpn].interface, vpns[vpn].interface, ipaddr)
        rooter("srcroute_disable", vpns[vpn].rt_table, ipaddr)

    exit(error)
